from rtdt.models import RTDTRecord

from django.contrib.contenttypes.models import ContentType
from django.core.cache import cache
from django.db.models.signals import post_save, post_delete
from django.conf import settings

# If you don't have this signal, get the patch from
# http://code.djangoproject.com/ticket/5390 and apply it to your copy
# of Django
try:
    from django.db.models.signals import m2m_changed
except ImportError:
    m2m_changed = None

def __rtdt_flush_object(object):
    if settings.DEBUG:
        print 'RTDT: Flushing %s instance "%s"' % (object.__class__, object)

    # Find every RTDT record for this id and contenttype
    drs = RTDTRecord.objects.filter(
        mid=object.id,
        model=ContentType.objects.get_for_model(object.__class__))

    # Extract the paths from these objects (will already be unique)
    paths = [i.path for i in drs]

    for path in paths:
        # Delete these paths from the cache and delete all RTDT records
        # that are associated with this path (including, naturally,
        # the objects from which we calculated these paths)
        if settings.DEBUG:
            print 'RTDT: Wiping cache entry for "%s"' % path
        cache.delete(path)
        RTDTRecord.objects.filter(path=path).delete()

def __rtdt_post_save_cb(sender, instance, created, **kwargs):
    # If this object was just created, it can't possibly have any rtdt
    # cache implications
    if created:
        return

    if settings.DEBUG:
        print 'RTDT: Saving %s instance "%s"' % (sender, instance)
    __rtdt_flush_object(instance)

def __rtdt_post_delete_cb(sender, instance, **kwargs):
    if settings.DEBUG:
        print 'RTDT: Deleting %s instance "%s"' % (sender, instance)
    __rtdt_flush_object(instance)

def __rtdt_m2m_changed_cb(sender, instance, action, model, field_name, \
                             reverse, objects, **kwargs):
    if settings.DEBUG:
        print 'RTDT: m2m %s' % action

    # "add" and "remove" are called after the change has been made,
    # but "clear" is called before, and objects is empty.
    if action == "clear":
        map(__rtdt_flush_object, getattr(instance, field_name).all())
    else:
        map(__rtdt_flush_object, objects)

    __rtdt_flush_object(instance)

_rtdt_registered_models = []

def register(model):
    post_save.connect(__rtdt_post_save_cb, sender=model)
    post_delete.connect(__rtdt_post_delete_cb, sender=model)
    if m2m_changed is not None:
        m2m_changed.connect(__rtdt_m2m_changed_cb, sender=model)

    _rtdt_registered_models.append(model)
